
//--------------------------------------------------------------------------------------
// Constant Buffer Variables
//--------------------------------------------------------------------------------------
matrix View;
matrix Projection;
float Time;
float RibbonShift;
float ParticlesShift;

Texture2D GroundTexture;
Texture2D RibbonTexture;
Texture2D ParticleTexture;

SamplerState samLinear
{
    Filter = MIN_MAG_MIP_LINEAR;
    AddressU = Wrap;
    AddressV = Wrap;
};


//--------------------------------------------------------------------------------------
// PASS 0 - Ground
//--------------------------------------------------------------------------------------
struct VS_OUTPUT
{
    float4 Pos : SV_POSITION;
    float2 Tex : TEXCOORD;
};

// Vertex Shader P0
VS_OUTPUT VS0( float4 Pos : POSITION, 
                float3 Normal : NORMAL,
                float3 Tex : TEXCOORD0 )
{
    VS_OUTPUT output = (VS_OUTPUT)0;
    
    output.Pos = mul( Pos, View );
    output.Pos = mul( output.Pos, Projection );
    
    output.Tex = Tex.xy;
    
    return output;
}


// Pixel Shader P0
float4 PS0( VS_OUTPUT input ) : SV_Target
{
    return GroundTexture.Sample( samLinear, input.Tex );
}

BlendState NoBlending
{
    BlendEnable[0] = FALSE;
};


//--------------------------------------------------------------------------------------
// PASS 1 - Bush
//--------------------------------------------------------------------------------------

// Vertex Shader P1
VS_OUTPUT VS1( float4 Pos : POSITION, 
                float3 Normal : NORMAL,
                float3 Tex : TEXCOORD0 )
{
    VS_OUTPUT output = (VS_OUTPUT)0;
    
    float amp = Pos.y * 0.12 * sin( Pos.y + 2 * Time );
    Pos.x += amp;
    output.Pos = mul( Pos + float4(Tex.xyz, 0), View );
    output.Pos = mul( output.Pos, Projection );

    output.Tex.x = dot(Normal, float3(0.6, 0.8, 0));
    output.Tex.y = Pos.y * 0.2;
    return output;
}


// Pixel Shader P1
float4 PS1( VS_OUTPUT input ) : SV_Target
{
    float4 c0 = input.Tex.x * float4(0, 0.5, 0.2, 1);
    float4 c1 = float4(0.5, 0.2, 0.2, 1);
    float t = input.Tex.y;
    return (1-t) * c0 + t * c1;
}


//--------------------------------------------------------------------------------------
// PASS 2 - Ribbons
//--------------------------------------------------------------------------------------

// Pixel Shader P2
float4 PS2( VS_OUTPUT input ) : SV_Target
{
    float2 tex = float2(input.Tex.x + RibbonShift, input.Tex.y);
    float4 color = RibbonTexture.Sample( samLinear, tex );
    return color + float4(0, 0, 0.3, 0);
    //return float4(0,0,0,1);
}

BlendState SrcAlphaBlendingAdd
    {
        BlendEnable[0] = TRUE;
        SrcBlend = SRC_ALPHA;
        DestBlend = INV_SRC_ALPHA;
        BlendOp = ADD;
        SrcBlendAlpha = ZERO;
        DestBlendAlpha = ZERO;
        BlendOpAlpha = ADD;
        RenderTargetWriteMask[0] = 0x0F;
    };

//--------------------------------------------------------------------------------------
// PASS 3 - Particles
//--------------------------------------------------------------------------------------

struct VS_OUTPUT3
{
    float4 Pos : SV_POSITION;
    float3 Tex : TEXCOORD;
};

// Vertex Shader P3
VS_OUTPUT3 VS3( float4 Pos : POSITION, 
                float3 Tex : TEXCOORD0,
                float3 C1 : TEXCOORD1,
                float3 C2 : TEXCOORD2 )
{
    VS_OUTPUT3 output = (VS_OUTPUT3)0;
    float t = frac(Tex.z + ParticlesShift);
    float3 center = (1 - t) * C1 + t * C2;
    float4 wp = float4(center,1);
    output.Pos = mul(wp, View);
    output.Pos += Pos;
    output.Pos = mul( output.Pos, Projection );
    output.Tex.xy = Tex.xy;
    output.Tex.z = clamp((center.y - 2) * 0.1, 0, 1);
    
    return output;
}

// Pixel Shader P3
float4 PS3( VS_OUTPUT3 input ) : SV_Target
{
    //float2 tex = float2(input.Tex.x + RibbonShift, input.Tex.y);
    float4 color = ParticleTexture.Sample( samLinear, input.Tex.xy );
    return color * float4(0, 0.3, 0, input.Tex.z);
    //return float4(0,0,0,1);
}

//--------------------------------------------------------------------------------------
technique10 Render
{
    pass P0
    {
        SetVertexShader( CompileShader( vs_4_0, VS0() ) );
        SetGeometryShader( NULL );
        SetPixelShader( CompileShader( ps_4_0, PS0() ) );
        SetBlendState( NoBlending, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
    }

    pass P1
    {
        SetVertexShader( CompileShader( vs_4_0, VS1() ) );
        SetGeometryShader( NULL );
        SetPixelShader( CompileShader( ps_4_0, PS1() ) );
        SetBlendState( NoBlending, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
    }

    pass P2
    {
        SetVertexShader( CompileShader( vs_4_0, VS0() ) );
        SetGeometryShader( NULL );
        SetPixelShader( CompileShader( ps_4_0, PS2() ) );
        SetBlendState( SrcAlphaBlendingAdd, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
    }

    pass P3
    {
        SetVertexShader( CompileShader( vs_4_0, VS3() ) );
        SetGeometryShader( NULL );
        SetPixelShader( CompileShader( ps_4_0, PS3() ) );
        SetBlendState( SrcAlphaBlendingAdd, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
    }
}

